package cn.schoolwow.quickdao.module.entity.flow.annotation;

import cn.schoolwow.quickdao.annotation.Comment;
import cn.schoolwow.quickdao.annotation.CompositeIndex;
import cn.schoolwow.quickdao.annotation.CompositeIndexes;
import cn.schoolwow.quickdao.annotation.UniqueField;
import cn.schoolwow.quickdao.domain.database.ddl.IndexField;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ScanTableAnnotationFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        Entity entity = (Entity) flowContext.checkData("entity");

        Comment comment = getFirstAnnotation(entity.clazz, Comment.class);
        if (null != comment) {
            entity.comment = comment.value();
        }
        List<CompositeIndex> compositeIndexList = new ArrayList<>();
        CompositeIndex compositeIndexAnno = getFirstAnnotation(entity.clazz, CompositeIndex.class);
        if (null != compositeIndexAnno) {
            compositeIndexList.add(compositeIndexAnno);
        }
        CompositeIndexes compositeIndexes = getFirstAnnotation(entity.clazz, CompositeIndexes.class);
        if (null != compositeIndexes) {
            compositeIndexList.addAll(Arrays.asList(compositeIndexes.value()));
        }
        if (compositeIndexList.size() > 0) {
            int indexFieldNameCount = 0;
            for (CompositeIndex compositeIndex : compositeIndexList) {
                if (compositeIndex.columns().length == 0) {
                    continue;
                }
                IndexField indexField = new IndexField();
                indexField.tableName = entity.tableName;
                indexField.indexType = compositeIndex.indexType();
                indexField.using = compositeIndex.using();
                for (String column : compositeIndex.columns()) {
                    indexField.columns.add(entity.getColumnNameByFieldName(column));
                }
                indexField.comment = compositeIndex.comment();
                if (!compositeIndex.indexName().isEmpty()) {
                    indexField.indexName = compositeIndex.indexName();
                } else {
                    indexField.indexName = entity.tableName + "_" + indexField.indexType.name().toLowerCase() + (indexFieldNameCount++);
                }
                entity.indexFieldList.add(indexField);
            }
        }
        UniqueField uniqueField = getFirstAnnotation(entity.clazz, UniqueField.class);
        if (null != uniqueField) {
            for (String column : uniqueField.columns()) {
                Property property = entity.getPropertyByFieldNameOrColumnName(column);
                if (null == property) {
                    throw new IllegalArgumentException("UniqueField注解参数无法匹配字段!类:" + entity.clazz.getName() + ",字段:" + column);
                }
                entity.uniqueProperties.add(property);
            }
        }
    }

    @Override
    public String name() {
        return "扫描实体类注解";
    }

    /**
     * 自下而上查找注解
     *
     * @param clazz 类
     */
    private <T> T getFirstAnnotation(Class clazz, Class<T> annotation) {
        T annotation1 = null;
        while (null != clazz && null == annotation1) {
            annotation1 = (T) clazz.getDeclaredAnnotation(annotation);
            clazz = clazz.getSuperclass();
        }
        return annotation1;
    }
}
